#include "unp.h"
#include "util.h"
#include "error.h"

void str_echo(int sockfd)
{
    ssize_t n;
    char buf[MAXLINE];
again:
    while ((n = Readline(sockfd, buf, MAXLINE)) > 0)
        Writen(sockfd, buf, n);

    if (n < 0 && errno == EINTR)
        goto again;
    else if (n < 0)
        err_sys("str_echo: read error");
}

void sig_chld(int signo)
{
    pid_t pid;
    int stat;

    while ((pid = waitpid(-1, &stat, WNOHANG)) > 0)
        printf("child %d terminated\n", pid);
    return;
}

int main(int argc, char **argv)
{
    int listenfd, connfd;
    pid_t childpid;
    socklen_t chilen;
    struct sockaddr_in cliaddr, servaddr;
    
    listenfd = Socket(AF_INET, SOCK_STREAM, 0);
    bzero(&servaddr, sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
    servaddr.sin_port = htons(SERV_PORT);
    
    Bind(listenfd, (SA *)&servaddr, sizeof(servaddr));

    Listen(listenfd, LISTENQ);
    
    signal(SIGCHLD, sig_chld);
    for (;;)
    {
        chilen = sizeof(cliaddr);
        connfd = Accept(listenfd, (SA*) &cliaddr, &chilen);
        if ((childpid = fork()) == 0)
        {
            // child process
            Close(listenfd);
            str_echo(connfd);
            exit(0);
        }
        // parent close connected socket
        Close(connfd);
    }
    Close(listenfd);
    exit(EXIT_SUCCESS);
}
